package com.kedll.library.widget;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Scroller;

import com.kedll.library.R;
import com.kedll.library.util.MyUtils;


/**
 * Created by dingrui on 16/4/8.
 * 自定义开关
 */
public class MySwitchView extends View {

    private final int[] SWITCH_CLOSE_COLOR = {0xffffffff, 0xffdedfe0};// 默认开关关闭颜色
    private final int SWITCH_OPEN_COLOR = 0xff4699df;// 默认开关打开的颜色
    private final int CIRCLE_COLOR = 0xffffffff;// 默认开关圆圈的颜色

    private int[] switchCloseColor = SWITCH_CLOSE_COLOR;// 开关关闭颜色
    private int switchOpenColor = SWITCH_OPEN_COLOR;// 开关打开的颜色
    private int circleColor = CIRCLE_COLOR;// 开关圆圈的颜色

    private boolean mIsCheck;// true:开关打开；false:开关关闭
    private Scroller mScroller;// 滚动类
    private int touchSpacing;// 默认响应距离
    private int margin;// 边距
    private boolean isMove;// 是否移动中
    private boolean isNotifyInterface = true;// 本次外部更改开关状态是否通知到接口

    private Paint mPaint;// 画笔

    private float x,// 记录当前x位置
            y;// 记录当前y位置

    private float downX,// 按下的x位置
            downY;// 按下的y位置

    private final int MODE_0 = 0,// 没有任何手势产生或点击
            MODE_1 = 1,// 上下滑动
            MODE_2 = 2,// 向左滑动
            MODE_3 = 3,// 向右滑动
            MODE_4 = 4;// 左右滑动

    private int mode = MODE_0;// 默认没有任何手势产生或点击

    /**
     * 接口
     */
    private OnCheckListener l;// 监听接口

    public MySwitchView(Context context) {
        this(context, null, 0);
    }

    public MySwitchView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MySwitchView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public MySwitchView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context,attrs);
    }

    /**
     * 初始化
     */
    private void init(Context context, AttributeSet attrs) {
        mScroller = new Scroller(getContext());
        touchSpacing = ViewConfiguration.get(getContext()).getScaledTouchSlop() / 2;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        margin = MyUtils.dp2px(1f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBackground(canvas);
        if (isMove) {
            drawCircleChange(canvas);
        } else {
            drawCircle(canvas);
        }
        if (!isEnabled()) {
            drawObscure(canvas);
        }
    }

    /**
     * 绘制背景
     *
     * @param canvas
     */
    private void drawBackground(Canvas canvas) {
        if (switchCloseColor == null) {
            switchCloseColor = SWITCH_CLOSE_COLOR;
        }
        if (switchCloseColor.length == 1) {
            mPaint.setColor(switchCloseColor[0]);
            mPaint.setStyle(Paint.Style.FILL);
            RectF mRectF = new RectF();
            mRectF.left = 0;
            mRectF.top = 0;
            mRectF.right = getWidth();
            mRectF.bottom = getHeight();
            canvas.drawRoundRect(mRectF,
                    getHeight() / 2, getHeight() / 2, mPaint);
        } else {
            mPaint.setColor(switchCloseColor[0]);
            mPaint.setStyle(Paint.Style.FILL);
            RectF mRectF = new RectF();
            mRectF.left = 0 + margin / 2.0f;
            mRectF.top = 0 + margin / 2.0f;
            mRectF.right = getWidth() - margin / 2.0f;
            mRectF.bottom = getHeight() - margin / 2.0f;
            canvas.drawRoundRect(mRectF,
                    getHeight() / 2, getHeight() / 2, mPaint);

            mPaint.setColor(switchCloseColor[1]);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(margin);
            RectF mRectF1 = new RectF();
            mRectF1.left = 0 + margin / 2.0f;
            mRectF1.top = 0 + margin / 2.0f;
            mRectF1.right = getWidth() - margin / 2.0f;
            mRectF1.bottom = getHeight() - margin / 2.0f;
            canvas.drawRoundRect(mRectF1,
                    getHeight() / 2, getHeight() / 2, mPaint);
        }
    }

    /**
     * 绘制圆圈
     *
     * @param canvas
     */
    private void drawCircle(Canvas canvas) {
        if (mIsCheck) {
            mPaint.setColor(switchOpenColor);
            mPaint.setStyle(Paint.Style.FILL);
            RectF mRectF = new RectF();
            mRectF.left = 0;
            mRectF.top = 0;
            mRectF.right = getWidth();
            mRectF.bottom = getHeight();
            canvas.drawRoundRect(mRectF,
                    getHeight() / 2, getHeight() / 2, mPaint);

            mPaint.setColor(circleColor);
            mPaint.setStyle(Paint.Style.FILL);
            canvas.drawCircle(
                    getWidth() - getHeight() / 2,
                    getHeight() / 2, getHeight() / 2 - margin, mPaint);

            mPaint.setColor(switchCloseColor[1]);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(margin);
            canvas.drawCircle(
                    getWidth() - getHeight() / 2,
                    getHeight() / 2, getHeight() / 2 - margin, mPaint);
        } else {

            mPaint.setColor(circleColor);
            mPaint.setStyle(Paint.Style.FILL);
            canvas.drawCircle(
                    getHeight() / 2,
                    getHeight() / 2, getHeight() / 2 - margin, mPaint);

            mPaint.setColor(switchCloseColor[1]);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(margin);
            canvas.drawCircle(
                    getHeight() / 2,
                    getHeight() / 2, getHeight() / 2 - margin, mPaint);
        }
    }

    /**
     * 绘制蒙板
     *
     * @param canvas
     */
    private void drawObscure(Canvas canvas) {
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAlpha(153);
        RectF mRectF = new RectF();
        mRectF.left = 0;
        mRectF.top = 0;
        mRectF.right = getWidth();
        mRectF.bottom = getHeight();
        canvas.drawRoundRect(mRectF,
                getHeight() / 2, getHeight() / 2, mPaint);
    }

    float r;

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (getWidth() > getHeight()) {
            r = 255.0f / (float) (getWidth() - getHeight());
        }
    }

    /**
     * 滚动时绘制圆圈
     *
     * @param canvas
     */
    private void drawCircleChange(Canvas canvas) {
        mPaint.setColor(switchOpenColor);
        int alpha = 255;
        if (r > 0) {
            alpha = (int) ((x - getHeight() / 2) * r);
        }
        mPaint.setAlpha(alpha);
        mPaint.setStyle(Paint.Style.FILL);
        RectF mRectF = new RectF();
        mRectF.left = 0;
        mRectF.top = 0;
        mRectF.right = getWidth();
        mRectF.bottom = getHeight();
        canvas.drawRoundRect(mRectF,
                getHeight() / 2, getHeight() / 2, mPaint);

        mPaint.setColor(circleColor);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(
                x,
                y, getHeight() / 2 - margin, mPaint);
        mPaint.setColor(switchCloseColor[1]);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(margin);
        canvas.drawCircle(
                x,
                y, getHeight() / 2 - margin, mPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                mode = MODE_0;
                getParent().requestDisallowInterceptTouchEvent(true);
                return true;

            case MotionEvent.ACTION_MOVE:
                if (mode == MODE_0 &&
                        Math.abs(event.getX() - downX) >= touchSpacing &&
                        Math.abs(event.getY() - downY) < touchSpacing &&
                        event.getX() <= getWidth() && event.getX() >= getWidth() - getHeight()
                        && mIsCheck) {
                    mode = MODE_2;
                } else if (mode == MODE_0 &&
                        Math.abs(event.getX() - downX) >= touchSpacing &&
                        Math.abs(event.getY() - downY) < touchSpacing &&
                        event.getX() >= 0 && event.getX() <= getHeight()
                        && !mIsCheck) {
                    mode = MODE_3;
                } else if (mode == MODE_0 &&
                        Math.abs(event.getX() - downX) >= touchSpacing &&
                        Math.abs(event.getY() - downY) < touchSpacing) {
                    mode = MODE_4;
                } else if (mode == MODE_0 &&
                        Math.abs(event.getX() - downX) < touchSpacing &&
                        Math.abs(event.getY() - downY) >= touchSpacing) {
                    mode = MODE_1;
                }
                if (mode == MODE_1) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                } else if (mode == MODE_2 || mode == MODE_3) {
                    if (!isEnabled()) {
                        return true;
                    }
                    if (!mScroller.isFinished())
                        return true;
                    isMove = true;
                    if (mode == MODE_2) {
                        x = event.getX() + touchSpacing;
                    } else if (mode == MODE_3) {
                        x = event.getX() - touchSpacing;
                    }
                    y = getHeight() / 2;
                    if (x > getWidth() - getHeight() / 2) {
                        x = getWidth() - getHeight() / 2;
                    }
                    if (x < getHeight() / 2) {
                        x = getHeight() / 2;
                    }
                    invalidate();
                }
                return true;

            case MotionEvent.ACTION_UP:
                getParent().requestDisallowInterceptTouchEvent(false);
                if (!isEnabled()) {
                    return true;
                }
                if (mode != MODE_0) {
                    if (mode == MODE_2 || mode == 3) {
                        if (!mScroller.isFinished())
                            return true;
                        if (x < getWidth() / 2) {
                            mScroller.startScroll((int) x,
                                    getHeight() / 2, (int) -(x - getHeight() / 2),
                                    0, (int) Math.abs(x - getHeight() / 2));
                        } else {
                            mScroller.startScroll((int) x,
                                    getHeight() / 2, (int) (getWidth() - getHeight() / 2 -
                                            x),
                                    0, (int) Math.abs(getWidth() - getHeight() / 2 -
                                            x));
                        }
                        isMove = false;
                        invalidate();
                    }
                    return true;
                }
                click();
                return true;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            isMove = true;
            x = mScroller.getCurrX();
            y = mScroller.getCurrY();
            if (mScroller.isFinished()) {
                if (x < getWidth() / 2) {
                    if (mIsCheck) {
                        mIsCheck = false;
                        if (l != null && isNotifyInterface) {
                            l.onCheck(this, mIsCheck);
                        }
                    }
                } else {
                    if (!mIsCheck) {
                        mIsCheck = true;
                        if (l != null && isNotifyInterface) {
                            l.onCheck(this, mIsCheck);
                        }
                    }
                }
                isNotifyInterface = true;
                isMove = false;
            }
            invalidate();
        }
    }

    /**
     * 点击事件
     */
    private void click() {
        if (!mScroller.isFinished())
            return;
        if (mIsCheck) {
            mScroller.startScroll(getWidth() - getHeight() / 2,
                    getHeight() / 2, -(getWidth() - getHeight() / 2 - getHeight() / 2),
                    0, getWidth());
        } else {
            mScroller.startScroll(getHeight() / 2,
                    getHeight() / 2, getWidth() - getHeight() / 2 - getHeight() / 2,
                    0, getWidth());
        }
        invalidate();
    }

    /**
     * 监听接口
     */
    public interface OnCheckListener {
        void onCheck(View v, boolean isCheck);
    }

    /**
     * 设置监听接口
     *
     * @param l
     */
    public void setOnCheckListener(OnCheckListener l) {
        this.l = l;
    }

    /**
     * 设置开关关闭颜色
     *
     * @param switchCloseColors 第一个元素是背景色
     *                          第二个元素是边线色
     *                          注意：设置一个时只绘制背景色
     */
    public void setSwitchCloseColor(int... switchCloseColors) {
        this.switchCloseColor = switchCloseColors;
    }

    /**
     * 设置开关开启颜色
     *
     * @param switchOpenColor
     */
    public void setSwitchOpenColor(int switchOpenColor) {
        this.switchOpenColor = switchOpenColor;
    }

    /**
     * 设置开关圆圈色
     *
     * @param circleColor
     */
    public void setCircleColor(int circleColor) {
        this.circleColor = circleColor;
    }

    /**
     * 设置开关开启关闭（没有动画）
     *
     * @param isCheck
     */
    public void setCheck(boolean isCheck) {
        if (!isEnabled())
            return;
        this.mIsCheck = isCheck;
        invalidate();
    }

    /**
     * 设置开关开启关闭（有动画）
     *
     * @param isCheck
     * @param isNotifyInterface 本次更改开关状态是否通知到接口（仅一次有效）
     */
    public void clickCheck(boolean isCheck, boolean isNotifyInterface) {
        if (!isEnabled()) {
            return;
        }
        if (this.mIsCheck != isCheck) {
            clickCheck(isNotifyInterface);
        }
    }

    /**
     * 外部调用点击事件
     *
     * @param isNotifyInterface 本次更改开关状态是否通知到接口（仅一次有效）
     */
    public void clickCheck(boolean isNotifyInterface) {
        if (!isEnabled())
            return;
        this.isNotifyInterface = isNotifyInterface;
        click();
    }

    /**
     * 获取开关当前状态
     *
     * @return
     */
    public boolean isCheck() {
        return mIsCheck;
    }

    @Override
    public void setEnabled(boolean enabled) {
//        if (!enabled) {
//            if (isCheck) {
//                isNotifyInterface = false;
//                click();
//                return;
//            }
//        }
        super.setEnabled(enabled);
    }
}
